import numpy as np
import os
from scipy.optimize import least_squares

class AbaqusInpParser:
    def __init__(self, file_path,park_name):
        self.file_path = file_path
        self.park_name = park_name
        self._nodes = []           # 存储原始节点数据
        self._elements = []        # 存储原始单元数据

        self.FRP_set_labels = [] # 当前集合的节点标签
        self.Tbar_set_labels = []
        self.Cbar_set_labels = []
        self.Sbar_set_labels = []

        # 最终输出的NumPy数组
        self.nodes_array = None    # 节点数组，格式：[[id, x, y], ...]
        self.elements_array = None # 单元数组

        self.FRP_nodes_set_array = None # 原始和处理后的集合节点数组，格式[原始,处理后],处理后：[[60000+id, x, y], ...]
        self.Tbar_nodes_set_array = None # 原始和处理后的集合节点数组
        self.Cbar_nodes_set_array = None # 原始和处理后的集合节点数组
        self.Sbar_nodes_set_array = None # 原始和处理后的集合节点数组

        # 状态标志
        self._reading_nodes = False
        self._reading_elements = False
        self._reading_sets_FRP = False
        self._reading_sets_Tbar = False
        self._reading_sets_Cbar = False
        self._reading_sets_Sbar = False

        self.elem_labels = {
            'FRP':None,
            'Tbar':None,
            'Cbar':None,
            'Sbar':None
        }

    def get_set_nodes(self, set_labels, offset=60000, is_sbar=False):
        """根据集合名称获取节点坐标数组，处理Sbar首尾节点为纵筋标签"""
        # 获取节点ID列表
        node_ids = np.array(set_labels, dtype=np.int64)
        
        # 从nodes_array中提取节点
        if self.nodes_array.size == 0:
            return [np.array([]), np.array([])]
            
        mask = np.isin(self.nodes_array[:, 0], node_ids)
        origin_nodes = self.nodes_array[mask].copy()
        
        # 根据指定算法排序
        if not is_sbar:
            sorted_origin = self._sort_by_x(origin_nodes)
        
        # 如果是Sbar，处理首尾节点
        if is_sbar:
            # 获取Cbar和Tbar的偏移后节点
            cbar_origin = self.Cbar_nodes_set_array[1]
            tbar_origin = self.Tbar_nodes_set_array[1]
            
            # 按极角分组
            groups = self._group_by_angle(origin_nodes)
            processed_groups = []
            
            for group in groups:
                if len(group) < 2:
                    processed_groups.append(group)
                    continue
                
                # 替换首节点为Cbar的节点
                end_node = group[-1]
                cbar_match = self._find_matching_node(end_node, cbar_origin)
                if cbar_match is not None:
                    end_node = cbar_match
                
                # 替换尾节点为Tbar的节点
                start_node = group[0]
                tbar_match = self._find_matching_node(start_node, tbar_origin)
                if tbar_match is not None:
                    start_node = tbar_match
                
                # 仅偏移中间节点
                middle_nodes = group[1:-1]
                if len(middle_nodes) > 0:
                    middle_nodes = self._apply_offset(middle_nodes, offset)
                
                # 合并首尾和中间
                processed_group = np.vstack([start_node, middle_nodes, end_node])
                processed_groups.append(processed_group)
            offset_data = np.array(processed_groups)
            sorted_origin = np.array(groups)
            nodes_set_array = offset_data
        else:
            # 普通集合：直接应用偏移
            nodes_set_array = self._apply_offset(sorted_origin, offset)
        
        return [sorted_origin, nodes_set_array]

    def _find_matching_node(self, node, target_nodes):
        """在目标节点数组中查找坐标相同的节点"""
        for n in target_nodes:
            if np.allclose(node[1:3], n[1:3]):  # 假设坐标在第1、2列
                return n
        return None

    
    def get_set_nodes_all(self):
        self.FRP_nodes_set_array = self.get_set_nodes(set_labels=self.FRP_set_labels,offset=600000)
        self.Tbar_nodes_set_array = self.get_set_nodes(set_labels=self.Tbar_set_labels,offset=700000)
        self.Cbar_nodes_set_array = self.get_set_nodes(set_labels=self.Cbar_set_labels,offset=800000)
        self.Sbar_nodes_set_array = self.get_set_nodes(set_labels=self.Sbar_set_labels,offset=900000,is_sbar=True)



    def parse(self):
        """主方法，解析INP文件并提取节点和单元信息"""
        with open(self.file_path, 'r') as f:
            lines = f.readlines()
            current_part = False
            self._reset_reading_flags()
            #print(self._is_part_start(line=lines[2406].strip()))

            for line in lines:
                line = line.strip()
                if not line:
                    continue

                # 判断当前行是否为目标Part的开始或结束
                if self._is_part_start(line):
                    current_part = True
                    self._reset_reading_flags()
                    continue
                elif self._is_part_end(line) and current_part:
                    break

                # 如果当前行在目标Part内
                if current_part:
                    if self._is_node_section(line):
                        self._reset_reading_flags(keep_nodes=True)
                        continue
                    elif self._is_element_section(line):
                        self._reset_reading_flags(keep_elements=True)
                        continue
                    elif self._is_set_section(line):
                        self._reset_reading_flags()
                        if self._is_node_set(line,set_name='FRP'):   #判断是否为FRP筋的线集合
                            self._reset_reading_flags(keep_sets_FRP=True)
                            continue
                        if self._is_node_set(line,set_name='Tbar'):   #判断是否为纵向受拉钢筋的线集合
                            self._reset_reading_flags(keep_sets_Tbar=True)
                            continue
                        if self._is_node_set(line,set_name='Cbar'):   #判断是否为纵向受压钢筋的线集合
                            self._reset_reading_flags(keep_sets_Cbar=True)
                            continue
                        if self._is_node_set(line,set_name='Sbar'):   #判断是否为箍筋的线集合
                            self._reset_reading_flags(keep_sets_Sbar=True)
                            continue
                        continue

                    # 提取节点、单元和集合信息
                    if self._reading_nodes:
                        self._parse_node_line(line)
                    elif self._reading_elements:
                        self._parse_element_line(line)
                    elif self._reading_sets_FRP:
                        self.FRP_set_labels.extend(self._parse_set_line(line))
                    elif self._reading_sets_Tbar:
                        self.Tbar_set_labels.extend(self._parse_set_line(line))
                    elif self._reading_sets_Cbar:
                        self.Cbar_set_labels.extend(self._parse_set_line(line))
                    elif self._reading_sets_Sbar:
                        self.Sbar_set_labels.extend(self._parse_set_line(line))

        # 转换为NumPy数组
        nodes_array = np.array(self._nodes, dtype=np.float64) if self._nodes else np.array([])
        elements_array = np.array(self._elements, dtype=np.int64) if self._elements else np.array([])
        self.nodes_array = nodes_array
        self.elements_array = elements_array

#------------------------------------ 辅助方法 ------------------------------------------------#
    def _reset_reading_flags(self, keep_nodes=False, keep_elements=False, keep_sets_FRP=False,
                             keep_sets_Tbar=False,keep_sets_Cbar=False,keep_sets_Sbar=False):
        """重置读取状态标志"""
        self._reading_nodes = keep_nodes
        self._reading_elements = keep_elements
        self._reading_sets_FRP = keep_sets_FRP
        self._reading_sets_Tbar = keep_sets_Tbar
        self._reading_sets_Sbar = keep_sets_Sbar
        self._reading_sets_Cbar = keep_sets_Cbar

    def _apply_offset(self, nodes_array, offset):
        """应用ID偏移的通用方法"""
        if offset == 0:
            return nodes_array
        sorted_nodes = nodes_array.copy()
        sorted_nodes[:, 0] += offset
        return sorted_nodes


 #---------------------------------- 解析判断方法 --------------------------------------------#
    def _is_part_start(self, line):
        """判断是否为Part的开始行"""
        return line.startswith(f'*Part, name={self.park_name}')

    def _is_part_end(self, line):
        """判断是否为Part的结束行"""
        return line.startswith('*End Part')

    def _is_node_section(self, line):
        """判断是否为节点部分的开始行"""
        return line.startswith('*Node')

    def _is_element_section(self, line):
        """判断是否为单元部分的开始行"""
        return line.startswith('*Element')
    
    def _is_set_section(self, line):
        """判断是否为集合部分的开始行"""
        return line.startswith('*Nset') or line.startswith('*Elset')
    
    def _is_node_set(self, line,set_name):
        """判断是否为FRP集合部分的开始行"""
        return line.startswith(f'*Nset, nset={set_name}')

#------------------------------------ 数据解析方法 -------------------------------------#
    def _parse_node_line(self, line):
        """解析节点行"""
        parts = [p.strip() for p in line.split(',')]
        if len(parts) >= 3:
            try:
                node_id = int(parts[0])
                x = float(parts[1])
                y = float(parts[2])
                self._nodes.append([node_id, x, y])
            except ValueError:
                pass  # 忽略格式错误的行

    def _parse_element_line(self, line):
        """解析单元行"""
        parts = [p.strip() for p in line.split(',')]
        if len(parts) >= 5:
            try:
                elem_id = int(parts[0])
                elem_nodes = list(map(int, parts[1:5]))
                self._elements.append([elem_id] + elem_nodes)
            except ValueError:
                pass  # 忽略格式错误的行

    def _parse_set_line(self, line):
        """解析集合行,并得到行的坐标"""
        labels = list(map(int, line.replace(',', ' ').split()))
        return labels
    

#------------------------------------ 数据排列算法 ------------------------------------------------#

    def _group_by_angle(self, nodes_array, angle_tol=1.0):
        """按极角分组箍筋节点（沿径向的线为一组）"""
        if len(nodes_array) == 0:
            return []
    
        # 计算隧道中心
        center = self._calc_tunnel_center(nodes_array=self.Tbar_nodes_set_array[0])
    
        # 计算每个节点的极角（角度，单位：度）
        vectors = nodes_array[:, 1:3] - center
        angles_deg = np.degrees(np.arctan2(vectors[:,1], vectors[:,0]))  # [-180, 180]
        
        
        # 将角度转换为0-360范围
        angles_deg = np.where(angles_deg < 0, angles_deg + 360, angles_deg)
        
        
        # 按角度排序
        sorted_indices = np.argsort(-angles_deg)
        sorted_angles = angles_deg[sorted_indices]
        sorted_nodes = nodes_array[sorted_indices]
    
        # 动态分组（角度变化超过阈值则分新组）
        groups = []
        current_group = [sorted_nodes[0]]
        prev_angle = sorted_angles[0]
    
        for i in range(1, len(sorted_angles)):
            angle_diff = abs(sorted_angles[i] - prev_angle)
            
            # 处理角度环绕（例如 355° 和 5° 实际相差10°）
            angle_diff = min(angle_diff, 360 - angle_diff)
            
            if angle_diff > angle_tol:
                sorted_group = self._sort_single_hoop(np.array(current_group), center)
                groups.append(sorted_group)
                current_group = []
            current_group.append(sorted_nodes[i])
            prev_angle = sorted_angles[i]
        
        if len(current_group) > 0:
            sorted_group = self._sort_single_hoop(np.array(current_group), center)
            groups.append(sorted_group)
        
        return groups

    def _sort_single_hoop(self, nodes, center):
        """对单条箍筋的节点按半径从小到大排序（沿径向排列）"""
        # 计算节点到隧道中心的距离（半径）
        vectors = nodes[:, 1:3] - center
        radii = np.linalg.norm(vectors, axis=1)
        
        # 按半径升序排序（从中心向外）
        sorted_indices = np.argsort(radii)
        sorted_nodes = nodes[sorted_indices]
        
        return sorted_nodes

    def _calc_tunnel_center(self, nodes_array):
        """计算隧道中心（新增圆形拟合方法）"""
        if nodes_array.size == 0:
            return np.array([0.0, 0.0])
        
        # 提取节点坐标
        points = nodes_array[:, 1:3].astype(float)
        
        # 定义残差函数（最小二乘拟合）
        def residuals(params, x):
            xc, yc, r = params
            return np.sqrt((x[:,0]-xc)**2 + (x[:,1]-yc)**2) - r
        
        # 初始猜测（使用包围盒中心法估计）
        x_min, y_min = np.min(points, axis=0)
        x_max, y_max = np.max(points, axis=0)
        x0 = [(x_min+x_max)/2, (y_min+y_max)/2, (x_max-x_min)/2]
        
        # 执行拟合
        result = least_squares(residuals, x0, args=(points,))
        xc, yc, _ = result.x
        return np.array([xc, yc])

    def _sort_by_x(self, nodes_array):
        """仅按X坐标排序算法（不处理Y坐标）"""
        if len(nodes_array) == 0:
            return nodes_array
        
        # 直接对X坐标使用argsort
        sorted_indices = np.argsort(nodes_array[:, 1])  # 第1列是X坐标
        return nodes_array[sorted_indices]


#------------------------------------ 生成输出数据 -------------------------------------#

    def _format_nodes_set_array(self,nodes_set_array):
            """将nodes_set_array转换为INP格式字符串列表"""
            formatted = []
            for node in nodes_set_array:
                # 格式化ID为整数，坐标保留原有精度
                node_id = int(node[0])
                x = node[1]
                y = node[2]
                # 根据数值大小调整格式
                if abs(x) < 1e-10:   # 接近零时简化为"0."
                    x_str = "0."
                else:
                    # 保留最多8位小数，并删除末尾多余的零和小数点
                    x_str = f"{x:.8f}".rstrip('0').rstrip('.') if '.' in f"{x:.8f}" else f"{x:.0f}."
                    
                if abs(y) < 1e-10:
                    y_str = "0."
                else:
                    y_str = f"{y:.8f}".rstrip('0').rstrip('.') if '.' in f"{y:.8f}" else f"{y:.0f}."
                
                formatted.append(f"{node_id:>6d}, {x_str:>12s}, {y_str:>12s}\n")
            return formatted
        
    def _format_COH2D4(self, node_array_list,start_elem_id=990001):
        """生成COH2D4单元格式字符串列表（每行形如'20001, 60001, 60002, 2, 1'）"""
        origin_nodes_set_array = node_array_list[0]
        nodes_set_array = node_array_list[1]
        formatted = []
        elem_ids_COH2D4 = []
        if (origin_nodes_set_array.size < 1 or 
            nodes_set_array.size < 1 or 
            len(origin_nodes_set_array) != len(nodes_set_array)):
            return formatted,elem_ids_COH2D4
        
        # 提取原始和偏移后的节点ID
        origin_ids = origin_nodes_set_array[:, 0].astype(int)
        offset_ids = nodes_set_array[:, 0].astype(int)
        
        # 每对相邻节点生成一个单元
        formatted.append("*Element, type=COH2D4\n")
        for i, elem_id in enumerate(range(start_elem_id, start_elem_id + len(origin_ids) - 1)):
            off1 = offset_ids[i]
            off2 = offset_ids[i+1]
            orig1 = origin_ids[i+1]  # 注意原始节点顺序反向
            orig2 = origin_ids[i]
            formatted.append(f"{elem_id:>6d}, {off1:>6d}, {off2:>6d},{orig1:>6d}, {orig2:>6d}\n")
            elem_ids_COH2D4.append(elem_id)  # 收集单元ID

        return formatted,elem_ids_COH2D4
    
    def _format_T2D2(self, nodes_set_array,start_elem_id=5500001):
        """生成T2D2单元格式字符串列表（每行形如'101, 60001, 60002'）"""
        formatted = []
        elem_ids_T2D2 = []
        if nodes_set_array is None or len(nodes_set_array) < 2:
            return formatted,elem_ids_T2D2
        
        # 提取偏移后的节点ID（确保按原始顺序排列）
        node_ids = nodes_set_array[:, 0].astype(int)
        
        # 每两个连续节点生成一个单元
        formatted.append("*Element, type=T2D2\n")
        for i, elem_id in enumerate(range(start_elem_id, start_elem_id + len(node_ids) - 1)):
            n1 = node_ids[i]
            n2 = node_ids[i+1]
            formatted.append(f"{elem_id:>6d}, {n1:>6d}, {n2:>6d}\n")
            elem_ids_T2D2.append(elem_id)  # 收集单元ID
        
        return formatted,elem_ids_T2D2

    def _format_T2D2_stirrup(self,start_elem_id=8800001):
        stirrup_format_list = []
        stirrup_format_list.append("*Element, type=T2D2\n")
        all_elem_ids = []
        for group in self.Sbar_nodes_set_array[1]:
            stirrup_elem, stirrup_elem_ids= self._format_T2D2(nodes_set_array=group,start_elem_id=start_elem_id)
            stirrup_format_list.extend(stirrup_elem[1:])
            all_elem_ids.extend(stirrup_elem_ids)
            start_elem_id += len(group)-1

        return stirrup_format_list,all_elem_ids

    def _format_COH2D4_stirrup(self,start_elem_id=9900001):
        stirrup_format_list = []
        stirrup_format_list.append("*Element, type=COH2D4\n")
        all_elem_ids = []
        for i in range(len(self.Sbar_nodes_set_array[1])):
            origin_data = self.Sbar_nodes_set_array[0][i]
            offset_data = self.Sbar_nodes_set_array[1][i]
            stirrup_elem, stirrup_elem_ids = self._format_COH2D4(node_array_list=[origin_data,offset_data],start_elem_id=start_elem_id)
            stirrup_format_list.extend(stirrup_elem[1:])
            all_elem_ids.extend(stirrup_elem_ids)
            start_elem_id += len(origin_data)-1

        return stirrup_format_list,all_elem_ids

    
    def _format_T2D2_section(self, elem_ids_T2D2,material_name="FRP", area=50.265, elset_name="FRP_BAR"):
        """生成T2D2单元的截面属性定义"""
        section = []
        if not elem_ids_T2D2:
            return section
        
        # 生成单元集合定义
        section.append(f"*Elset, elset={elset_name}, generate\n")
        section.append(f"{min(elem_ids_T2D2)}, {max(elem_ids_T2D2)}, 1\n")
        
        # 生成截面属性
        section.append(f"*Solid Section, elset={elset_name}, material={material_name}\n")
        section.append(f"{area:.2f},\n")  # 截面积参数
        return section

    def _format_COH2D4_section(self,elem_ids_COH2D4, material_name="Cohesive", thickness=50.265,
                               response_type="TRACTION SEPARATION", elset_name="FRP_COH2D4"):
        """生成COH2D4单元的粘聚层属性定义"""
        section = []
        if not elem_ids_COH2D4:
            return section
        
        # 生成单元集合定义
        section.append(f"*Elset, elset={elset_name}, generate\n")
        section.append(f"{min(elem_ids_COH2D4)}, {max(elem_ids_COH2D4)}, 1\n")
        
        # 生成粘聚层属性
        section.append(
            f"*Cohesive Section, elset={elset_name}, "
            f"material={material_name}, response={response_type}, thickness=SPECIFIED\n"
        )
        section.append(f"1.,{thickness:.4f},\n")  # 粘聚层厚度
        return section

    
    
#------------------------------------ 输出inp_with_cohesive -------------------------------------#
    def insert_data(self, original_lines, insert_marker, prepend_data, offset_lines=0):
        """
        增强版数据插入方法，支持多标记判断
        :param insert_marker: 主标记或标记列表
        :param insert_marker1: 附加标记（可选）
        """
        if len(prepend_data) < 1:
            return original_lines
        # 构建标记列表
        markers = []
        if isinstance(insert_marker, (list, tuple)):
            markers.extend(insert_marker)
        else:
            markers.append(insert_marker)
    
        current_part = False
        # 查找所有匹配行位置
        marker_index  = None
        for i, line in enumerate(original_lines):
            # 判断当前行是否为目标Part的开始或结束
            if self._is_part_start(line):
                current_part = True
                continue
            elif self._is_part_end(line) and current_part:
                break

            if current_part:
                stripped = line.strip()
                for marker in markers:
                    if stripped.startswith(marker):
                        marker_index  = i
                        break  # 避免重复匹配
            if marker_index is not None:
                break  # 完全退出循环
    
        if marker_index is None:
            raise ValueError(f"未找到任何标记行: {markers}")
    
        modified_lines = original_lines.copy()
        
        insert_pos = marker_index  + offset_lines
        # 插入数据块（带前后空行）
        modified_lines[insert_pos:insert_pos] = prepend_data
    
        return modified_lines

    def output_inp(self):
        """将修改后的内容输出到同一目录下的新文件"""
        # 获取原始文件路径信息
        dir_path = os.path.dirname(self.file_path)     # 原始文件所在目录
        base_name = os.path.basename(self.file_path)   # 原始文件名
        new_filename = f"modified_{base_name}"         # 新文件名
        output_path = os.path.join(dir_path, new_filename)  # 完整输出路径

        # 读取原始内容
        with open(self.file_path, 'r') as f:
            original_lines = f.readlines()

        #--------------------- 输出节点 ---------------#
        FRP_node = self._format_nodes_set_array(nodes_set_array=self.FRP_nodes_set_array[1])
        modified_lines = self.insert_data(original_lines=original_lines,insert_marker='*Element',prepend_data=FRP_node)

        Tbar_node = self._format_nodes_set_array(nodes_set_array=self.Tbar_nodes_set_array[1])
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker='*Element',prepend_data=Tbar_node)

        Cbar_node = self._format_nodes_set_array(nodes_set_array=self.Cbar_nodes_set_array[1])
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker='*Element',prepend_data=Cbar_node)

        Sbar_node = self._format_nodes_set_array(nodes_set_array=self.Sbar_nodes_set_array[1][:,1:-1].reshape(-1, 3))
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker='*Element',prepend_data=Sbar_node)

        #--------------------- 输出T2D2单元 ---------------#
        FRP_elemT2D2,FRP_elemT2D2_ids = self._format_T2D2(nodes_set_array=self.FRP_nodes_set_array[1],start_elem_id=5500001)
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker=['*Nset','*Elset'],prepend_data=FRP_elemT2D2)

        Tbar_elemT2D2,Tbar_elemT2D2_ids = self._format_T2D2(nodes_set_array=self.Tbar_nodes_set_array[1],start_elem_id=6600001)
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker=['*Nset','*Elset'],prepend_data=Tbar_elemT2D2)

        Cbar_elemT2D2,Cbar_elemT2D2_ids = self._format_T2D2(nodes_set_array=self.Cbar_nodes_set_array[1],start_elem_id=7700001)
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker=['*Nset','*Elset'],prepend_data=Cbar_elemT2D2)

        Sbar_elemT2D2,Sbar_elemT2D2_ids = self._format_T2D2_stirrup(start_elem_id=8800001)
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker=['*Nset','*Elset'],prepend_data=Sbar_elemT2D2)

        #--------------------- 输出COH2D4单元 ---------------#
        FRP_elemCOH2D4 ,FRP_elemCOH2D4_ids= self._format_COH2D4(node_array_list=self.FRP_nodes_set_array,start_elem_id=9500001)
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker=['*Nset','*Elset'],prepend_data=FRP_elemCOH2D4)

        Tbar_elemCOH2D4 ,Tbar_elemCOH2D4_ids= self._format_COH2D4(node_array_list=self.Tbar_nodes_set_array,start_elem_id=9600001)
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker=['*Nset','*Elset'],prepend_data=Tbar_elemCOH2D4)

        Cbar_elemCOH2D4 ,Cbar_elemCOH2D4_ids= self._format_COH2D4(node_array_list=self.Cbar_nodes_set_array,start_elem_id=9700001)
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker=['*Nset','*Elset'],prepend_data=Cbar_elemCOH2D4)

        Sbar_elemCOH2D4 ,Sbar_elemCOH2D4_ids= self._format_COH2D4_stirrup(start_elem_id=9800001)
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker=['*Nset','*Elset'],prepend_data=Sbar_elemCOH2D4)


        #--------------------- 输出T2D2单元截面 ---------------#
        FRP_T2D2_section = self._format_T2D2_section(elem_ids_T2D2=FRP_elemT2D2_ids,material_name="FRP", area=50.265, elset_name="FRP_T2D2")
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker=['*Nset','*Elset'],prepend_data=FRP_T2D2_section)

        Tbar_T2D2_section = self._format_T2D2_section(elem_ids_T2D2=Tbar_elemT2D2_ids,material_name="Lbar", area=785.398, elset_name="Tbar_T2D2")
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker=['*Nset','*Elset'],prepend_data=Tbar_T2D2_section)

        Cbar_T2D2_section = self._format_T2D2_section(elem_ids_T2D2=Cbar_elemT2D2_ids,material_name="Lbar", area=785.398, elset_name="Cbar_T2D2")
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker=['*Nset','*Elset'],prepend_data=Cbar_T2D2_section)

        Sbar_T2D2_section = self._format_T2D2_section(elem_ids_T2D2=Sbar_elemT2D2_ids,material_name="Sbar", area=615.752, elset_name="Sbar_T2D2")
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker=['*Nset','*Elset'],prepend_data=Sbar_T2D2_section)

        #--------------------- 输出COH2D4单元截面 ---------------#
        FRP_COH2D4_section = self._format_COH2D4_section(elem_ids_COH2D4=FRP_elemCOH2D4_ids, material_name="Cohesive_FRP", thickness=50.265,elset_name="FRP_COH2D4")
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker=['*Nset','*Elset'],prepend_data=FRP_COH2D4_section)

        Tbar_COH2D4_section = self._format_COH2D4_section(elem_ids_COH2D4=Tbar_elemCOH2D4_ids, material_name="Cohesive_Lbar", thickness=314.159,elset_name="Tbar_COH2D4")
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker=['*Nset','*Elset'],prepend_data=Tbar_COH2D4_section)

        Cbar_COH2D4_section = self._format_COH2D4_section(elem_ids_COH2D4=Cbar_elemCOH2D4_ids, material_name="Cohesive_Lbar", thickness=314.159,elset_name="Cbar_COH2D4")
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker=['*Nset','*Elset'],prepend_data=Cbar_COH2D4_section)

        Sbar_COH2D4_section = self._format_COH2D4_section(elem_ids_COH2D4=Sbar_elemCOH2D4_ids, material_name="Cohesive_Sbar", thickness=276.46,elset_name="Sbar_COH2D4")
        modified_lines = self.insert_data(original_lines=modified_lines,insert_marker=['*Nset','*Elset'],prepend_data=Sbar_COH2D4_section)

        #写入新文件（保留原始换行符）
        with open(output_path, 'w', newline='') as f:
            f.writelines(modified_lines)


    def main(self):
        self.parse()
        self.get_set_nodes_all()
        self.output_inp()
            
if __name__ == "__main__":
    current_directory = os.getcwd()
    log_files = [f for f in os.listdir(current_directory) if f.endswith('.inp')]
    for file in log_files:
        log_file_path = os.path.join(current_directory, log_files[0])
        log_file_path = os.path.abspath(log_file_path)
        
        parser = AbaqusInpParser(file_path=log_file_path,park_name='tunnel')
        parser.main()

        

